package com.lemobar.pay.utils.converter;

import com.lemobar.pay.model.notify.PayOrderNotifyResult;
import com.lemobar.pay.model.notify.WxPayOrderNotifyCoupon;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;
import org.apache.commons.lang3.StringUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Selier
 */
public class PayOrderNotifyResultConverter extends AbstractReflectionConverter {
    public PayOrderNotifyResultConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
        super(mapper, reflectionProvider);
    }

    @Override
    public boolean canConvert(Class type) {
        return type.equals(PayOrderNotifyResult.class);
    }

    @Override
    public void marshal(Object original, HierarchicalStreamWriter writer, MarshallingContext context) {
        super.marshal(original, writer, context);
        PayOrderNotifyResult obj = (PayOrderNotifyResult) original;
        List<WxPayOrderNotifyCoupon> list = obj.getCouponList();
        if (list != null && list.size() != 0) {
            for (int i = 0; i < list.size(); ++i) {
                WxPayOrderNotifyCoupon coupon = (WxPayOrderNotifyCoupon) list.get(i);
                writer.startNode("coupon_id_" + i);
                writer.setValue(coupon.getCouponId());
                writer.endNode();
                writer.startNode("coupon_type_" + i);
                writer.setValue(coupon.getCouponType());
                writer.endNode();
                writer.startNode("coupon_fee_" + i);
                writer.setValue(coupon.getCouponFee() + "");
                writer.endNode();
            }

        }
    }

    @Override
    protected void marshallField(MarshallingContext context, Object newObj, Field field) {
        if (!"couponList".equals(field.getName())) {
            super.marshallField(context, newObj, field);
        }
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        PayOrderNotifyResult obj = new PayOrderNotifyResult();
        List<Field> fields = new ArrayList(Arrays.asList(obj.getClass().getDeclaredFields()));
        fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields()));
        Map<String, Field> fieldMap = this.getFieldMap(fields);

        TreeMap coupons;
        for (coupons = new TreeMap(); reader.hasMoreChildren(); reader.moveUp()) {
            reader.moveDown();
            if (fieldMap.containsKey(reader.getNodeName())) {
                Field field = (Field) fieldMap.get(reader.getNodeName());
                this.setFieldValue(context, obj, field);
            } else {
                String type;
                if (StringUtils.startsWith(reader.getNodeName(), "coupon_id_")) {
                    type = (String) context.convertAnother(obj, String.class);
                    this.getElement(coupons, reader.getNodeName()).setCouponId(type);
                } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_type_")) {
                    type = (String) context.convertAnother(obj, String.class);
                    this.getElement(coupons, reader.getNodeName()).setCouponType(type);
                } else if (StringUtils.startsWith(reader.getNodeName(), "coupon_fee_")) {
                    Integer fee = (Integer) context.convertAnother(obj, Integer.class);
                    this.getElement(coupons, reader.getNodeName()).setCouponFee(fee);
                }
            }
        }
        List couponList = new ArrayList(coupons.values());
        obj.setCouponList(couponList);
        return obj;
    }

    private void setFieldValue(UnmarshallingContext context, PayOrderNotifyResult obj, Field field) {
        Object val = context.convertAnother(obj, field.getType());

        try {
            if (val != null) {
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());
                pd.getWriteMethod().invoke(obj, val);
            }
        } catch (Exception var6) {
        }

    }

    private Map<String, Field> getFieldMap(List<Field> fields) {
        return fields.stream().collect(Collectors.toMap(field -> field.isAnnotationPresent(XStreamAlias.class) ? field.getAnnotation(XStreamAlias.class).value() : field.getName(), field -> field));
    }

    private WxPayOrderNotifyCoupon getElement(Map<Integer, WxPayOrderNotifyCoupon> coupons, String nodeName) {
        Integer index = Integer.valueOf(StringUtils.substringAfterLast(nodeName, "_"));
        if (coupons.get(index) == null) {
            coupons.put(index, new WxPayOrderNotifyCoupon());
        }

        return coupons.get(index);
    }

}
